package vcp.server.requesthandler;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;

import ocsf.server.ConnectionToClient;

import org.joda.time.DateTime;
import org.joda.time.DateTimeComparator;

import vcp.client.request.SiteMapSaveRequest;
import vcp.client.request.response.ResponseRequest;
import vcp.entity.Car;
import vcp.entity.Lot;
import vcp.entity.Site;
import vcp.entity.utility.RobotManager;
import vcp.enums.LotStatus;
import vcp.server.DAO.CarDAO;
import vcp.server.DAO.LotDAO;
import vcp.server.DAO.SiteDAO;
import vcp.server.interfaces.IServer;
/**
 * 
 * @author VCP team
 *<p>
 *class that handles request from client and saves site map
 *</p>
 */
public class SiteMapSaveRequestHandler extends RequestHandler<SiteMapSaveRequest>
{
	/**
	 * class constructor
	 * @param server
	 */
	public SiteMapSaveRequestHandler(IServer server)
	{
		super(server);
	}

	@Override
	public void execute(SiteMapSaveRequest request, ConnectionToClient client)
	{
		LotDAO lotDao = new LotDAO();
		SiteDAO siteDAO = new SiteDAO();
		CarDAO carDAO = new CarDAO();

		Site site = request.getSite();

		int countDamaged = 0;
		int countReserved = 0;

		StringBuilder notificationBuilder = new StringBuilder();
		notificationBuilder.append("The following cars cannot be resereved for this site:\n");
		boolean willHaveNotification = false;
		boolean robotModified = false;

		Iterator<Lot> iterator = site.getParkingMatrix().iterator();
		while (iterator.hasNext())
		{
			Lot lot = iterator.next();
			if (lot.isChanged())
			{
				switch (lot.getLotStatus())
				{
					case NON_WORKING:
						countDamaged++;
						lotDao.updateBrokeStartDate(lot.getParentSite().getSiteID(), lot.getFloor(), lot.getRow(), lot.getColumn(), lot.getBrokeStartDate());
						lotDao.updateLotStatusByID(site.getSiteID(), lot.getFloor(), lot.getRow(), lot.getColumn(), lot.getLotStatus());
						break;
					case RESERVE:
						boolean reserevedSuccesfully = false;
						Car car = carDAO.findByID(lot.getCarID());
						if (car != null)
						{
							if (!lotDao.isCarRegisteredOnSiteLot(site.getSiteID(), car.getCarID()))
							{
								lot.setReservedBySubscription(car.getSubscriptionID());

								lotDao.updateCarInLot(site.getSiteID(), lot.getFloor(), lot.getRow(), lot.getColumn(), lot.getCarID());
								lotDao.updateReservedBySubscription(site.getSiteID(), lot.getFloor(), lot.getRow(), lot.getColumn(), lot.getReservedBySubscription());

								countReserved++;
								reserevedSuccesfully = true;
								lotDao.updateLotStatusByID(site.getSiteID(), lot.getFloor(), lot.getRow(), lot.getColumn(), lot.getLotStatus());
							}
						}

						if (!reserevedSuccesfully)
						{
							willHaveNotification = true;

							String prefix = car == null ? "Non subscriber car " : "Already reserved car ";
							notificationBuilder.append(prefix + lot.getCarID() + " on floor:" + lot.getFloor() + ";(" + lot.getRow() + "," + lot.getColumn() + ")\n");
							lot.setLotStatus(LotStatus.FREE);
							lot.setCarID(null);
						}

						break;
					case FREE:
						if (DateTimeComparator.getDateOnlyInstance().compare(lot.getBrokeStartDate(), new DateTime(2001, 1, 1, 0, 0, 0).getMillis()) != 0)
						{
							lotDao.updateBrokeEndDate(lot.getParentSite().getSiteID(), lot.getFloor(), lot.getRow(), lot.getColumn(), lot.getBrokeEndDate());
							lotDao.updateLotStatusByID(site.getSiteID(), lot.getFloor(), lot.getRow(), lot.getColumn(), lot.getLotStatus());
							RobotManager.getRobotManagerInstance().getSiteRobot(lot.getParentSite().getSite()).removeCar();
							robotModified=true;
						}
					default:
						break;
				}

				lot.setChanged(false);
			}
		}

		siteDAO.updateDamagedLotsByID(site.getSiteID(), countDamaged);
		siteDAO.updateReservedLotsByID(site.getSiteID(), countReserved);

		ArrayList<Serializable> serializableInfo = new ArrayList<>();

		if(robotModified)
		{
			siteDAO.getSiteLotsOnDemand(site);
		}


		serializableInfo.add(site);
		if (willHaveNotification)
		{
			serializableInfo.add(notificationBuilder.toString());
		}

		this.sendResponseRefresh(site, client);
		this.sendResponse(new ResponseRequest(request.getRequestID(), serializableInfo), client);
	}
}
